package mn.more.wits.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.rpc.AsyncCallback;
import mn.more.wits.client.dto.Handshake;
import mn.more.wits.client.dto.Payload;
import mn.more.wits.client.dto.UserDTO;
import mn.more.wits.client.gui.Headmast;
import mn.more.wits.client.gui.StatusBar;
import mn.more.wits.client.util.BrowserUtil;
import mn.more.wits.client.util.ClientModelUtil;
import net.mygwt.ui.client.Registry;
import net.mygwt.ui.client.Style;
import net.mygwt.ui.client.widget.Viewport;
import net.mygwt.ui.client.widget.layout.BorderLayout;
import net.mygwt.ui.client.widget.layout.BorderLayoutData;

/**
 * @author $Author: mikeliucc $
 * @version $Revision: 119 $
 */
public class WitsMain implements EntryPoint {

	public static final String ID_VIEWPORT = "viewport";
	private static final AppMsg APP_MSG = AppMsg.Self.get();

	private BorderLayout borderLayout = new BorderLayout();
	private Viewport viewport = new Viewport();
	private Headmast headmast = new Headmast();
	private MainPanel main = new MainPanel();
	private StatusBar statusBar = new StatusBar();
	private GetCurrentAuthCallback currentAuthCallback = new GetCurrentAuthCallback();

	/** callback for app. handshake */
	private class AppReadyCallback implements AsyncCallback {

		public void onFailure(Throwable caught) {
			// we are not expecting error here.  But if we do, it means that the server is still not ready to receive
			// client.  For example, maybe the server is still booting up, or it has some serious network issues.
			initViewPort();
			hideSplashScreen();
			String title = APP_MSG.serverConnectionErrTitle();
			String message = APP_MSG.serverConnection2Busy();
			String redirectURL = APP_MSG.serverNonGwtHomePage();
			AppContext.notifyCloseApp(title, message, redirectURL);
		}

		public void onSuccess(Object result) {
			Handshake handshake = (Handshake) result;
			if (handshake.getStatus() != Handshake.STATUS_RED) {
				AppContext.setHandshake(handshake);
				AuthProvider.App.getInstance().getAuth(currentAuthCallback);
			} else {
				// a "RED" status means that the server is "overloaded" with too many client
				// in such case, we should discontinue any new clients until the server's load is lessen to
				// a more manageable capacity -- this is analogous to "pausing" a Windows service.
				initViewPort();
				hideSplashScreen();
				String title = APP_MSG.serverConnectionErrTitle();
				String message = APP_MSG.serverConnection2Busy();
				String redirectURL = APP_MSG.serverNonGwtHomePage();
				AppContext.notifyCloseApp(title, message, redirectURL);
			}
		}
	}

	/** callback for checking current auth object */
	private class GetCurrentAuthCallback implements AsyncCallback {

		public void onFailure(Throwable e) {
			initViewPort();
			hideSplashScreen();
			AppContext.notifyCloseApp("WITS", e.getMessage(), APP_MSG.serverNonGwtHomePage());
		}

		public void onSuccess(Object o) {
			initViewPort();
			if (o == null) {
				// not yet logged in.
				AppContext.showLoginPage();
			} else {
				// already logged in and session is still valid.
				Payload payload = (Payload) o;
				UserDTO user = new UserDTO();
				ClientModelUtil.toModel(payload, user);
				// save user for later reference.
				AppContext.setUser(user);
				AppContext.showStartPage();
			}
			hideSplashScreen();
		}
	}

	public void onModuleLoad() {
		viewport.setId(ID_VIEWPORT);
		Registry.register(ID_VIEWPORT, viewport);

		// these are the basic steps...
		// 1. handshake: "handshake" with server-side to get the TEA key
		// 2. check if the current user has an existing auth available
		// 3. if user already logged in, redirect to the start page
		//    if user is not, show the login page
		ServiceInit.App.getInstance().init(AppContext.APP_NAME, new AppReadyCallback());
	}

	private void initViewPort() {
		borderLayout.setMargin(0);
		borderLayout.setSpacing(0);

		viewport.setBorders(false);
		viewport.setLayout(borderLayout);

		viewport.add(headmast, new BorderLayoutData(Style.NORTH, 65, 65, 65));
		viewport.add(statusBar, new BorderLayoutData(Style.SOUTH, 35, 35, 35));
		viewport.add(main, new BorderLayoutData(Style.CENTER));
	}

	private void hideSplashScreen() {
		BrowserUtil.hide(DOM.getElementById("splash"));
		//RootPanel.get().setVisible(true);
		viewport.layout(true);
		viewport.show();
	}

}
